using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace DataBroker.Dao
{
    /// <summary>
    /// This class supports joins between entitites. All standard
    /// SQL join types are supported.
    /// </summary>
    [Serializable]
    public class JoinTypeEnumeration
    {

        /// <summary>
        /// INNER join
        /// </summary>
        static public readonly JoinTypeEnumeration INNER = new JoinTypeEnumeration(1);
        /// <summary>
        /// Left Outer join
        /// </summary>
        static public readonly JoinTypeEnumeration LEFT_OUTER = new JoinTypeEnumeration(2);

        /// <summary>
        /// Right Outer join
        /// </summary>
        static public readonly JoinTypeEnumeration RIGHT_OUTER = new JoinTypeEnumeration(3);

        /// <summary>
        /// Full Outer join
        /// </summary>
        static public readonly JoinTypeEnumeration FULL_OUTER = new JoinTypeEnumeration(4);

        /// <summary>
        /// Cross join
        /// </summary>
        static public readonly JoinTypeEnumeration CROSS = new JoinTypeEnumeration(5);

        /// <summary>
        /// Internal flag describing how this binding relates to the
        /// previous binding in a search criteria.
        /// </summary>
        private int joinType;

        // --------------------------------------------------------- CLASS CONSTRUCTORS    

        /// <summary>
        /// Default constructor.
        /// </summary>
        public JoinTypeEnumeration()
        {

        }

        /// <summary>
        /// Private constructor for static variables.
        /// </summary>
        /// <param name="jt"></param>
        private JoinTypeEnumeration(int jt)
        {
            joinType = jt;
        }


        /// <summary>
        /// Returns the current boolean operator.
        /// </summary>
        /// <returns>Current boolean operator.</returns>
        public override String ToString()
        {
            switch (joinType)
            {
                case 1:
                    {
                        return " INNER JOIN ";
                    }
                case 2:
                    {
                        return " LEFT OUTER JOIN ";
                    }
                case 3:
                    {
                        return " RIGHT OUTER JOIN ";
                    }
                case 4:
                    {
                        return " FULL OUTER JOIN ";
                    }
                case 5:
                    {
                        return " CROSS JOIN ";
                    }
                default:
                    {
                        return "UNKNOWN";
                    }
            }
        } // END OF toString

    }

    /// <summary>
    /// Represents a join between two tables. The join is constructed by declaring
    /// collections of child Entities in an entity class and creating a list through
    /// the constructor when a join is needed.
    /// </summary>
    public class DBJoin
    {
        /***
        * The first tableName in the join.
        ******/
        private List<string> _first = new List<string>();

        /***
         * The second tableName in the join.
         ******/
        private List<string> _second = new List<string>();


        private JoinTypeEnumeration _joinType;


        /// <summary>
        /// Constructor required by serialization.
        /// </summary>

        public DBJoin()
        {
            _joinType = JoinTypeEnumeration.INNER;
        }

        /// <summary>
        /// Constructs a new join that joins using the first field to the second field.
        /// </summary>
        /// <param name="first">The first field</param>
        /// <param name="second">The second field</param>
        public DBJoin(String first, String second)
        {
            _joinType = JoinTypeEnumeration.INNER;
            _first.Add(first);
            _second.Add(second);
        }

        /// <summary>
        /// Constructs a new join that joins using the first field to the second field.
        /// </summary>
        /// <param name="first">The first field</param>
        /// <param name="second">The second field</param>
        /// <param name="joinType">Type of join.</param>
        public DBJoin(String first, String second, JoinTypeEnumeration joinType)
        {
            _joinType = joinType;
            _first.Add(first);
            _second.Add(second);
        }



        /// <summary>
        /// Join type enumeration.
        /// </summary>
        /// <returns>Join type enumeration</returns>
        public JoinTypeEnumeration JoinType()
        {
            return _joinType;
        }

        /// <summary>
        /// Constructs a new join that joins using the first field to the second field.
        /// </summary>
        /// <param name="first">The first field</param>
        /// <param name="second">The second field</param>
        [Obsolete("Use constructor with List<string> instead.")]
        public DBJoin(ArrayList first, ArrayList second)
        {
            _joinType = JoinTypeEnumeration.INNER;
            _first = new List<string>((string[])first.ToArray(typeof(string)));
            _second = new List<string>((string[])second.ToArray(typeof(string)));
        }

        /// <summary>
        /// Constructs a new join that joins using the first field to the second field.
        /// </summary>
        /// <param name="first">The first field</param>
        /// <param name="second">The second field</param>
        public DBJoin(List<string> first, List<string> second)
        {
            _joinType = JoinTypeEnumeration.INNER;
            _first = first;
            _second = second;
        }
        /// <summary>
        /// Constructs a new join that joins using the first field to the second field, with a
        /// join type.
        /// </summary>
        /// <param name="first">The first field</param>
        /// <param name="second">The second field</param>
        /// <param name="joinType">Join type.</param>
        [Obsolete("Use constructor with List<string> instead.")]
        public DBJoin(ArrayList first, ArrayList second, JoinTypeEnumeration joinType)
            : this(first, second)
        {
            _joinType = joinType;
        }

        /// <summary>
        /// Constructs a new join that joins using the first field to the second field, with a
        /// join type.
        /// </summary>
        /// <param name="first">The first field</param>
        /// <param name="second">The second field</param>
        /// <param name="joinType">Join type.</param>
        public DBJoin(List<string> first, List<string> second, JoinTypeEnumeration joinType)
            : this(first, second)
        {
            _joinType = joinType;
        }


        /// <summary>
        /// Converts the join into SQL.
        /// </summary>
        /// <returns>SQL for the join</returns>
        public override String ToString()
        {
            StringBuilder sResult = new StringBuilder("");
            int firstSize = _first.Count;
            int secondSize = _second.Count;
            if (firstSize > 1 && secondSize > 1 && firstSize == secondSize)
            {
                for (int i = 0; i < firstSize; i++)
                {
                    sResult.Append(_first[i] + " = " + _second[i]);
                    if (i < (firstSize - 1))
                    {
                        sResult.Append(" And ");
                    }
                }
                return sResult.ToString();
            }
            return (_first[0] + " = " + _second[0]);
        } // END OF toString

    }
}